<?php
/**
 * Copyright (c) [2019] [吴跃忠]
 * [selibra] is licensed under the Mulan PSL v1.
 * You can use this software according to the terms and conditions of the Mulan PSL v1.
 * You may obtain a copy of Mulan PSL v1 at:
 * http://license.coscl.org.cn/MulanPSL
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 * PURPOSE.
 * See the Mulan PSL v1 for more details.
 */

namespace Selibra\Http\Lib;


use Selibra\Http\Protocol\HttpResponseInterface;
use Swoole\Http\Response as SwooleHttpResponse;
use Selibra\Config\Config;
use Selibra\Tools\Console;

class Response implements HttpResponseInterface
{

    /**
     * 设置的头部信息
     * @var array
     */
    protected $headers = [];

    /**
     * @var string
     */
    private $type = 'text/html';


    /**
     * 已设置
     * @var bool
     */
    private $typeIsSet = false;


    /**
     *
     * @var string
     */
    private $charset = 'utf-8';


    /**
     * 返回内容
     * @var string
     */
    private $content;


    /**
     * http状态
     * @var int
     */
    private $status = 200;


    /**
     * 跳转地址
     * @var string
     */
    private $redirect;


    /**
     * @var int
     */
    public $code = 0;


    /**
     * @var string
     */
    protected $message;


    /**
     * @var SwooleHttpResponse
     */
    protected $swooleHttpResponse;

    public function __construct(SwooleHttpResponse $response)
    {
        $this->swooleHttpResponse = $response;
        $this->header('content-type', $this->type . '; charset=' . $this->charset);
    }


    /**
     * 设置或获取header信息
     * @param $key
     * @param null $value
     * @param array $ucwords
     * @return mixed
     */
    public function header($key, $value = null, $ucwords = [])
    {
        if (is_array($key)) {
            foreach ($key as $headerKey => $headerValue) {
                $this->header($headerKey, $headerValue);
            }
        } elseif (!empty($value)) {
            $this->headers[$key] = $value;
        } else {
            return $this->swooleHttpResponse->header($key, $value, $ucwords);
        }
        return true;
    }


    /**
     * 查询头部
     * @return array
     */
    public function selectHeaders()
    {
        return $this->headers;
    }


    /**
     * @return string
     */
    public function getType(): string
    {
        return $this->type;
    }


    /**
     * @param string $type
     * @return $this
     */
    public function setType(string $type)
    {
        $this->type = $type;
        $this->typeIsSet = true;
        return $this;
    }


    /**
     * 设置cookie信息
     * @param $name
     * @param null $value
     * @param null $expires
     * @param null $path
     * @param null $domain
     * @param null $secure
     * @param null $httponly
     */
    public function setCookie($name, $value = null, $expires = null, $path = null, $domain = null, $secure = null, $httponly = null)
    {
        $this->swooleHttpResponse->setCookie($name, $value, $expires, $path, $domain, $secure, $httponly);
    }


    /**
     * @return SwooleHttpResponse
     */
    public function sendfile($filename, $offset = null, $length = null)
    {
        return $this->swooleHttpResponse->sendfile($filename, $offset, $length);
    }


    /**
     * @return string
     */
    public function getCharset(): string
    {
        return $this->charset;
    }


    /**
     * @param string $charset
     * @return $this
     */
    public function setCharset(string $charset)
    {
        $this->charset = $charset;
        return $this;
    }


    /**
     * @return mixed
     */
    public function getContent()
    {
        $defaultType = Config::get('application.http.default_response_type');
        if (!$this->typeIsSet) {
            if ($defaultType === 'auto' && is_array($this->content)) {
                $this->setType('application/json');
            } else {
                $this->setType(empty($defaultType) || $defaultType === 'auto' ? $this->type : $defaultType);
            }
        }
        $data = $this->content;
        $this->header('content-type', $this->type . '; charset=' . $this->charset);
        return $data;
    }


    /**
     * @param mixed $content
     * @return $this
     */
    public function setContent($content)
    {
        $this->content = $content;
        return $this;
    }

    /**
     * @return int
     */
    public function getStatus(): int
    {
        return $this->status;
    }


    /**
     * @param int $status
     * @return $this
     */
    public function setStatus(int $status)
    {
        $this->status = $status;
        return $this;
    }


    /**
     * @param string $redirect
     */
    public function redirect(string $redirect)
    {
        $this->header('Location', $redirect);
        $this->redirect = $redirect;
    }


    /**
     * @param $code
     * @return $this
     */
    public function setCode($code)
    {
        $this->code = $code;
        return $this;
    }


    /**
     * @return int
     */
    public function getCode()
    {
        return $this->code;
    }


    /**
     * @return string
     */
    public function getResponseData()
    {
        $content = $this->getContent();
        if ($this->type === 'text/html') {
            return $content;
        } elseif (strpos($this->type, 'image/') === 0) {
            $this->header('Content-Type', $this->type);
            return $content;
        }
        $responseData = [
            'errcode' => $this->getCode() ?: 0,
            'message' => $this->getMessage() ?: null,
            'data' => $content ?: null,
        ];
        foreach ($responseData as $key => $datum) {
            if (null === $datum) {
                unset($responseData[$key]);
            }
        }
        return json_encode($responseData, JSON_UNESCAPED_UNICODE);
    }


    /**
     * 设置返回消息
     * @param $message
     * @return $this
     */
    public function setMessage($message)
    {
        $this->message = $message;
        return $this;
    }


    /**
     * 获取返回消息
     * @return string
     */
    public function getMessage()
    {
        return $this->message;
    }

}